上一篇提到有違和感的部份就是權限問題,在 post 的部份,update 和 destroy 這兩個方法其實應該要有所限制,也就是除了 admin 之外,只有該貼文的擁有者才能夠採取該方法。不過也可以直接在 controller 中直接透過 ORM 撈出該貼文所屬的使用者 id 以及是否為 admin,端看個人造化。
$post = Post::find($id);
$user_id = $post->user_id
Step 1 : 建立 Policy
$ php artisan make:policy PostPolicy
建立後的檔案,路徑與內容如下:
*app/Policies/PostPolicy.php
<?php
namespace App\Policies;
use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class PostPolicy
{
use HandlesAuthorization;
/**
* Create a new policy instance.
*
* @return void
*/
public function __construct()
{
//
}
}
若要自動產生CRUD method 的話
$ php artisan make:policy PostPolicy --model=Post
*app/Policies/PostPolicy.php
<?php
namespace App\Policies;
use App\Post;
use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class PostPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view any posts.
*
* @param \App\User $user
* @return mixed
*/
public function viewAny(User $user)
{
//
}
/**
* Determine whether the user can view the post.
*
* @param \App\User $user
* @param \App\Post $post
* @return mixed
*/
public function view(User $user, Post $post)
{
//
}
/**
* Determine whether the user can create posts.
*
* @param \App\User $user
* @return mixed
*/
public function create(User $user)
{
//
}
/**
* Determine whether the user can update the post.
*
* @param \App\User $user
* @param \App\Post $post
* @return mixed
*/
public function update(User $user, Post $post)
{
//
}
/**
* Determine whether the user can delete the post.
*
* @param \App\User $user
* @param \App\Post $post
* @return mixed
*/
public function delete(User $user, Post $post)
{
//
}
/**
* Determine whether the user can restore the post.
*
* @param \App\User $user
* @param \App\Post $post
* @return mixed
*/
public function restore(User $user, Post $post)
{
//
}
/**
* Determine whether the user can permanently delete the post.
*
* @param \App\User $user
* @param \App\Post $post
* @return mixed
*/
public function forceDelete(User $user, Post $post)
{
//
}
}
Step 2 : 註冊 Policy
*app/Providers/AuthServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use App\Post;
use App\Policies\PostPolicy;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
// 在此註冊 Policy
protected $policies = [
// 'App\Model' => 'App\Policies\ModelPolicy',
Post::class => PostPolicy::class,
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
//
}
}
Step 3 : 設計 Policy
update
use Illuminate\Auth\Access\Response;
/*
...
*/
public function update(User $user, Post $post)
{
return $user->id === $post->user_id || $user->is_admin;
}
delete ( 在 Policy 中 destroy 對應的是 delete)
use Illuminate\Auth\Access\Response;
/*
...
*/
public function delete(User $user, Post $post)
{
return $user->id === $post->user_id || $user->is_admin;
}
Step 4 : 引用 Policy
*PostsController@update
public function update(Request $request, $id)
{
$rules = [
'title' => 'string|min:2|max:500',
'content' => 'string|min:2|max:1500'
];
$validator = Validator::make($request->all(), $rules);
if($validator->fails()){
return response(['message' => $validator->errors()]);
}
$auth_user = request()->get('auth_user')->first();
$post = Post::find($id);
if(!is_null($post)){
// Policy Authorization
if($auth_user->can('update', $post)){
$post->update($request->only(['title', 'content']));
return response(['data' => $post]);
}else{
return response(['message' => 'Unauthorized!!']);
}
}else{
return response(['message' => 'Post not found!']);
}
}
*PostsController@destroy
public function destroy($id)
{
$auth_user = request()->get('auth_user')->first();
$post = Post::find($id);
if(!is_null($post)){
// Policy Authorization
if($auth_user->can('delete', $post)){
$post->delete();
return response(['message' => 'Post deleted!!']);
}else{
return response(['message' => 'Unauthorized!!']);
}
}else{
return response(['message' => 'Post not found!']);
}
}
以 update 為例
post 的部份到此結束,接下來就來處理 category。
參考資料: